/*
** File: hey_readline.c
** Desc: Contains the general hooks for reading a line
** Auth: Colm MacCarthaigh (colmmacc@redbrick.dcu.ie)
** Date: 5/9/01
**
** $Id: hey_readline.c,v 1.4 2004-02-19 21:50:34 c-hey Exp $
*/

/*
** this is some pretty complicated shit - but well worth it :)
** 
** ANSI escapes rock!
*/

#include <stdarg.h>
#include <string.h>
#include <stdio.h>

#include "hey_readline.h"
#include "hey_edit.h"
#include "hey_format.h"
#include "hey_arg.h"
#include "dyn_page.h"
#include "config.h"
#include "aux.h"

#ifdef HAVE_LIBREADLINE
/* <bobb> readline includes */
#include <readline/readline.h>
#include <readline/history.h>
#endif

#define LINESIZE 128            /* Should be plenty */

/* are we currently editing ? */
static	int 	 hey_editing;

#ifdef HAVE_LIBREADLINE
/* the line we are currently on */
int hey_line = 0;

/* the total number of lines */
int hey_linetotal = 0;

/* has the last line been appended */
int hey_lastdone = 0;

#endif


/* the expanded prompt */
char	*hey_rlprompt;


/* initialise readline stuff */
void hey_readline_init()
{
#ifdef HAVE_LIBREADLINE
	if (isatty(STDIN_FILENO))
	{
		/* every app should have this set */
		rl_readline_name = "hey";

		/* add our function names */
		rl_add_defun("hey_carriage_return", hey_return, -1);
		rl_add_defun("hey_line_up", hey_lineup, -1);
		rl_add_defun("hey_line_down", hey_linedown, -1);
		rl_add_defun("hey_arrows", hey_arrows, -1);
		rl_add_defun("hey_return", hey_return, -1);

		/* tell readline where to find bindings */
		rl_startup_hook = hey_bindkeys;
	}
#endif
	
	/* make sure prompt is set */
	if((hey_rlprompt = hey_generate_prompt()) == NULL) {
		hey_rlprompt = strdup("");
	}

	/* we are now editing */
	hey_editing = 1;

}

/* we are done reading lines */
void hey_readline_fini()
{

	/* we are done editing */
	hey_editing = 0;

	/* the prompt can upset error messages */
	if(strcmp(hey_rlprompt,"") && isatty(STDIN_FILENO))
		printf("\n");

	/* leaks are bad */
	free(hey_rlprompt);
}

/* actually read a line from standard input */
char *hey_readline(void)
{
	char	* line;
	static char buffer[LINESIZE];

	hey_line++;
	hey_linetotal++;
	hey_lastdone = 0;

#ifdef HAVE_LIBREADLINE
	if (isatty(STDIN_FILENO))
	{
		if((line = readline(hey_rlprompt)) == NULL) {
			return NULL;
		}
	}
	else
	{
		/* get the line */	
		if(!fgets(buffer, LINESIZE, stdin)) {
			return NULL;
		}

		/* chomp the line */
		if (strlen(buffer) > 1)
        		if (buffer[strlen(buffer) - 1] == '\n') buffer[strlen(buffer) - 1] = '\0';

		/* We'll need to return it */
		line = buffer;
	}
#else  /* HAVE_LIBREADLINE */

	if (isatty(STDIN_FILENO))
	{
		/* print the prompt */
		printf("%s", hey_rlprompt);
	}

	/* get the line */	
	if(!fgets(buffer,LINESIZE,stdin)) {
		return NULL;
	}

	/* chomp the line */
	if (strlen(buffer) > 1)
       		if (buffer[strlen(buffer) - 1] == '\n') buffer[strlen(buffer) -1] = '\0';

	line = buffer;
#endif

	/* test for EOF */
	if(hey_eof != NULL) {
		if(!strcmp(line, hey_eof)) {
			return NULL;
		}
	}

	/* throw it back */
	return line;
}


/* generate the hey prompt */
char *hey_generate_prompt(void) {
	char     *username;
	hey_user *user;
	char     *prompt_line;
	int       count;
	char     *ptr;
#define MINIBUFSIZE	16
	char     mini_buffer[MINIBUFSIZE];
	
	/* <x> This code is my fault. Blame me :) */
	if (hey_prompt) {

		/* Allocate initial space for the prompt_line */
		if ((prompt_line = malloc(1)) == NULL) {
			perror_exit("hey: Out of Memory while allocating prompt_line\n");
    	}
		
		*prompt_line = '\0';

	    /* Format the username string */
		/* Add the first user name we are heying */
		/* there will always be one .... */
		user = (hey_user *)g_listTraverse(hey_userlist);
		if (user) {
			username = strdup(user->name);
		} else {
			if((username = malloc(1)) == NULL) {
				perror_exit("hey: Out of Memory while allocating username\n");
			}
			*username = '\0';
		}

		/* Add additional names
	 	* If we have more than 4, we put in ... to show multiple users */
	    	for (count = 1; count < hey_nousers ; count++) {
			if (count < hey_maxnames) {
				user = (hey_user *)g_listTraverse(NULL);
				if(user != NULL) {
					username = m_strcat(username, " ");
					username = m_strcat(username, user->name);
				}
			} else {
		   		username = m_strcat(username," ...");
				break;
	        	}
		}

		/* do some search and replace */	
		for (ptr = hey_prompt; *ptr; ptr++) {
			if (*ptr == '%') {
				switch(*(ptr + 1)) {
					case '%':
						prompt_line = m_strcat(prompt_line, "%");
						ptr++;
						break;
							
					case 'u':
					case 'U':
						prompt_line = m_strcat(prompt_line, username);
						ptr++;
						break;

					case 'n':
					case 'N':
						snprintf(mini_buffer, MINIBUFSIZE, "%d", hey_nousers);
						prompt_line = m_strcat(prompt_line, mini_buffer);
						ptr++;
						break;
				
					default:
						snprintf(mini_buffer, MINIBUFSIZE, "%c", *ptr);
						prompt_line = m_strcat(prompt_line, mini_buffer);
						break;
				}		
			} else {
				snprintf(mini_buffer, MINIBUFSIZE, "%c", *ptr);
				prompt_line = m_strcat(prompt_line, mini_buffer);
			}
		}

		free(username);

	} else {
	    	prompt_line = NULL;
    	}
	
	return prompt_line;	
#undef MINIBUFSIZE
}

/* redisplays a hey's buffer after SIGCONT */
void hey_redisplay(void)
{
#ifndef HAVE_LIBREADLINE
	char * ptr;

	if(!hey_editing) return;

	if((ptr = dyn_pageRead(hey_page))) {    	
		do {
			/* We can't use printf, as it it not re-entrant */	
			write(STDOUT_FILENO, hey_rlprompt, strlen(heyrlprompt));
			write(STDOUT_FILENO, ptr, strlen(ptr));
			write(STDOUT_FILENO, "\n", sizeof("\n"));
		} while ((ptr = dyn_pageRead(NULL)));     
	}

	write(STDOUT_FILENO, hey_rlprompt, strlen(heyrlprompt));

	/* make sure it's all on screen */
	fflush(stdout);
#endif

#ifdef HAVE_LIBREADLINE
	if(!hey_editing) return;

	hey_refresh(0, 0);
#endif
}
